home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1996 #15
/
Monster Media Number 15 (Monster Media)(July 1996).ISO
/
prog_gen
/
wdj0796.zip
/
CC.ZIP
/
CC.C
next >
Wrap
C/C++ Source or Header
|
1994-02-02
|
43KB
|
1,300 lines
/* Note: this source code is really crappy, but it was written in
* a big hurry.
*/
/* SS != DS if DLL, fix for bcc and ztc */
/* disabling smart callbacks for bcc and ztc */
/*
* cc - Vendor-independent interface to C compilers.
*
* to build me, type "cc -dos -wild cc.c".
*/
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <errno.h>
#include <stdio.h>
#include <process.h>
#include <dos.h>
int Version = 0x0009;
#if defined(__BORLANDC__)
#include <io.h>
#include <fcntl.h>
#include <sys\stat.h>
#define WRITE write
#define OPEN open
#define CLOSE close
#define UNLINK unlink
#define STRICMP stricmp
#define CREAT creat
#elif defined(__ZTC__)
#include <io.h>
#define WRITE write
int _okbigbuf = 0; /* makes more memory available */
#define STRICMP strcmpl
#define spawnvp(a,b,c) spawnvp(a,b,(const char * const *)c)
#define execvp(b,c) execvp(b,(const char * const *)c)
#elif defined(_MSC_VER)
#include <io.h>
/* #include <sys\stat.h> */
/* #include <fcntl.h> */
#define OPEN open
#define CLOSE close
#define UNLINK unlink
#define CREAT creat
#define WRITE _write
#define STRICMP _stricmp
#endif
#define TRUE 1
#define FALSE 0
const char *Extensions = "c\0cpp\0res\0rc\0def\0obj\0lib\0lib0\0lib1\0\0";
enum { EXT_C=0, EXT_CPP, EXT_RES, EXT_RC, EXT_DEF, EXT_OBJ,
EXT_LIB, EXT_LIB0, EXT_LIB1, N_EXT };
typedef struct COMPILE_OPTIONS
{
int ProcessorType; /* 0=8088, 1=80186, etc. */
int Align; /* 1=byte align, 2=word align, etc. */
int CompileOnly; /* TRUE if compile only, no link */
char MemoryModel; /* 't' = tiny, 's' = small, etc. */
int SsNeqDs; /* TRUE if should assume SS != DS */
int Windows; /* TRUE = Windows, FALSE = DOS */
int Dll; /* TRUE = make .dll */
int Com; /* TRUE = make .com (for DOS) */
int Debug; /* 0=no debug, 1=line numbers, 2=all */
int StackCheck; /* TRUE=compile stack checks in */
int CPlusPlus; /* TRUE if using C++ instead of C */
char *RunName; /* Name to use for executable file */
int Windows30; /* TRUE if mark exe/dll for Windows 3.0 */
int MapFile; /* TRUE if we should generate map file */
int Verbose; /* TRUE if we are verbose! */
int WildCards; /* TRUE if command-line should handle wild-cards */
char Prologue; /* 'a' = AX, 's' = SS, 'd' = DGROUP, '\0' = default */
int NoSmart; /* TRUE if user wants no smart callbacks */
char *CodeSegment; /* name of code segment */
int Optimize; /* zero means no optimize */
char *LibName; /* name of library to update */
int Strict; /* =1 -> user did -DSTRICT
=0 -> user did nothing
=-1 -> user did -D */
} COMPILE_OPTIONS;
enum COMPILER_TYPE { MSC, BCC, SC };
typedef void (*COMPILER_FUNC) (enum COMPILER_TYPE , COMPILE_OPTIONS *);
typedef struct COMPILER
{
char *CompilerName;
enum COMPILER_TYPE CompilerType;
COMPILER_FUNC CompilerFunc;
} COMPILER;
void Msc(enum COMPILER_TYPE, COMPILE_OPTIONS *);
void Bcc(enum COMPILER_TYPE, COMPILE_OPTIONS *);
void Ztc(enum COMPILER_TYPE, COMPILE_OPTIONS *);
COMPILER Compilers[] =
{
{ "msc", MSC, Msc },
{ "bcc", BCC, Bcc },
{ "sc", SC, Ztc },
};
#define NCOMPILERS (sizeof(Compilers) / sizeof(COMPILER))
#define MAX_FILES 128
#define MAX_MACROS 128
int NMacros;
char *Macros[MAX_MACROS];
char *DefName;
char CommandLine[128];
char *UsageMessage =
"cc - Vendor-independent C/C++ Compilation (Windows/DOS Developer's Journal)\0"
"Usage: cc [options] sourcefiles\0"
"\0"
"-1 use 80186 instructions\0"
"-2 use 80286 instructions\0"
"-3 use 80386 instructions\0"
"-4 use 80486 instructions\0"
"-30 mark exe/dll 3.0 compatible\0"
"-a{1|2} byte or word alignment\0"
" (default is byte alignment)\0"
"-c compile only, no link\0"
"-com create .com (DOS only)\0"
"-C disable smart callbacks\0"
"-d include complete debug info\0"
"-dl include line numbers only\0"
"-Dname{=def} define macro\0"
"-dos compile/link for DOS\0"
"-mx{!} specify memory model:\0"
" t = tiny s = small\0"
" c = compact m = medium\0"
" l = large h = huge\0"
" ! means assume DS != SS\0"
" (the default for .dll)\0"
"-M don't generate map file\0"
"-NT<name> set name of code segment\0"
"-o<name> set name of target executable\0"
" name must end in .com, .exe, or .dll\0"
"-O optimize generated code\0"
"-p use C++ compiler\0"
"-s enable stack checks\0"
"-u<libname> Update library with .obj files\0"
"-v Verbose (don't delete .rsp files)\0"
"-w{e|d}{a|s|d}\0"
" | | (.exe default is SS)\0"
" | | (.dll default is DGROUP)\0"
" | +-> a=AX, s=SS, d=DGROUP\0"
" +-> e=.exe (default), d=.dll\0"
" default is -we (Windows .exe, use SS)\0"
"-wild link with special wildcard .obj\0"
"\0"
;
#define MAX_ARGS (64)
int NCmdArgs = 1;
char *CmdArgs[MAX_ARGS];
#include "common.c"
FileType FilesByExt[N_EXT];
FILE *OpenFile(const char *FileName, const char *Mode)
{
FILE *File;
File = fopen(FileName, Mode);
if(File == NULL)
{
fprintf(stderr, "Can't open '%s' for %s.\n", FileName,
(*Mode == 'w') ? "writing" : "reading");
exit(EXIT_FAILURE);
}
return File;
}
/* GetCompiler() return which vendor's compiler to use. */
COMPILER *GetCompiler(void)
{
char Buffer[64];
char *CC;
int i;
CC = getenv("CC");
if(CC && *CC)
{
char *Output = Buffer;
while(*CC != ' ' && *CC != '\0')
*Output++ = *CC++ | ' '; /* lowercase it */
*Output = '\0';
while(*CC == ' ')
++CC;
if(*CC)
CmdArgs[NCmdArgs++] = CC;
for(i = 0; i < NCOMPILERS; ++i)
if(!strcmp(Buffer, Compilers[i].CompilerName))
return &Compilers[i];
fprintf(stderr, "'%s': I do not recognize this compiler name "
"(defined in your\n"
" 'CC' environment variable. The names I recognize are:\n"
" ",
getenv("CC"));
for(i = 0; i < NCOMPILERS; ++i)
{
fprintf(stderr, "'%s'", Compilers[i].CompilerName);
if(i == (NCOMPILERS-2))
fprintf(stderr, " and ");
else if(i < (NCOMPILERS-1))
fprintf(stderr, ", ");
}
fprintf(stderr, "\n");
}
return 0;
}
void Usage(void)
{
int NLines;
char *Line1, *Line2;
Line1 = UsageMessage;
while(strlen(Line1)) /* blank line signals start of two-column */
{
fprintf(stderr, "%s\n", Line1);
Line1 += strlen(Line1)+1;
}
Line2 = ++Line1;
for(NLines = 0; strlen(Line2); ++NLines)
Line2 += strlen(Line2)+1;
Line2 = Line1;
NLines /= 2;
while(NLines-- > 0) /* Count total # of option lines */
Line2 += strlen(Line2)+1;
do {
int Column;
fprintf(stderr, " %s", Line1);
for(Column = strlen(Line1); Column < 36; ++Column)
fprintf(stderr, " ");
fprintf(stderr, "%s\n", Line2);
Line1 += strlen(Line1)+1;
if(*Line2)
Line2 += strlen(Line2)+1;
} while(*Line2);
exit(EXIT_FAILURE);
}
void ErrorOption(char *Arg)
{
ErrorOutput("'");
ErrorOutput(Arg);
ErrorOutput("': Unknown option\r\n");
}
int DoOption(char *OriginalArg, COMPILE_OPTIONS *Options)
{
char ModelChar = '\0';
char OptionChar;
char *Arg;
Arg = OriginalArg + 1; /* skip leading '-' or '/' */
OptionChar = *Arg++;
switch(OptionChar)
{
case '3' :
if(!strcmp(Arg, "0")) /* if option was "-30" */
{
Options->Windows30 = TRUE;
break;
}
case '0' :
case '1' :
case '2' :
case '4' :
Options->ProcessorType = OptionChar - '0';
if(*Arg)
ErrorOption(OriginalArg);
break;
case 'a' :
if(Arg[1] == '\0' &&
(*Arg == '1' || *Arg == '2'))
Options->Align = *Arg - '0';
else
ErrorOption(OriginalArg);
break;
case 'c' :
if(*Arg == '\0')
Options->CompileOnly = TRUE;
else if(!strcmp(OriginalArg, "-com"))
{
if(ModelChar && ModelChar != 't')
ErrorOutput("Only tiny memory model is compatible with .com file\r\n");
else
{
Options->MemoryModel = 't';
Options->Com = TRUE;
}
}
else
ErrorOption(OriginalArg);
break;
case 'C' :
if(*Arg == '\0')
Options->NoSmart = TRUE;
else
ErrorOption(OriginalArg);
break;
case 'd' : /* include debugging information */
if(*Arg == '\0')
Options->Debug = 2;
else if(!strcmp(OriginalArg, "-dl"))
Options->Debug = 1;
else if(!strcmp(OriginalArg, "-dos"))
Options->Windows = FALSE;
else
ErrorOption(OriginalArg);
break;
case 'D' :
if(!strcmp(OriginalArg, "-DSTRICT"))
Options->Strict = 1;
else if(*Arg == '\0')
Options->Strict = -1;
Macros[NMacros++] = OriginalArg;
break;
case 'M' :
Options->MapFile = FALSE;
break;
case 'm' :
switch(ModelChar = OptionChar = *Arg++)
{
case 's' :
case 'm' :
case 'l' :
case 'h' :
if(Options->Com)
{
ErrorOutput("You must use the tiny memory model to get a .com file\r\n");
OptionChar = 't';
}
case 't' :
if(ModelChar == 't')
{
Options->Com = TRUE;
Options->Windows = FALSE;
}
Options->MemoryModel = OptionChar;
OptionChar = *Arg++;
if(OptionChar)
{
if(OptionChar == '!')
Options->SsNeqDs = TRUE;
else
ErrorOption(OriginalArg);
}
break;
default :
ErrorOption(OriginalArg);
}
break;
case 'N' :
if(*Arg == 'T')
Options->CodeSegment = Arg+1;
else
ErrorOption(OriginalArg);
break;
case 'o' : /* specify executable filename */
if(!*Arg)
ErrorOption(OriginalArg);
else
{
char *Ext = FindExtension(Arg);
Options->RunName = Arg;
if(!STRICMP(Ext, "com"))
Options->Com = TRUE;
else if(!STRICMP(Ext, "dll"))
Options->Dll = Options->Windows = TRUE;
if(*Ext)
*--Ext = '\0';
}
break;
case 'O' :
if(*Arg)
ErrorOption(OriginalArg);
else
Options->Optimize = TRUE;
break;
case 'p' : /* use C++ compiler */
if(*Arg)
ErrorOption(OriginalArg);
else
Options->CPlusPlus = TRUE;
break;
case 's' : /* enable stack checks */
if(*Arg)
ErrorOption(OriginalArg);
else
Options->StackCheck = TRUE;
break;
case 'u' : /* update library */
if(*Arg)
Options->LibName = Arg;
else
ErrorOption(OriginalArg);
break;
case 'v' : /* be verbose # */
fprintf(stderr, "cc v%d.%d\n", Version>>8, Version&0x0FF);
Options->Verbose = TRUE;
break;
case 'w' : /* compile for Windows */
if(*Arg == '\0' || !strcmp(OriginalArg, "-we"))
{
Options->Prologue = 's';
Options->Windows = TRUE;
}
else if(!strcmp(OriginalArg, "-wd"))
{
Options->Prologue = 'd';
Options->Windows = TRUE;
Options->Dll = TRUE;
Options->SsNeqDs = TRUE;
}
else if(strchr("ed", OriginalArg[2])
&& strchr("ads", OriginalArg[3])
&& OriginalArg[4] == '\0')
{
Options->Windows = TRUE;
if(OriginalArg[2] == 'd')
{
Options->Dll = TRUE;
Options->SsNeqDs = TRUE;
}
Options->Prologue = OriginalArg[3];
}
else if(!strcmp(OriginalArg, "-wild"))
Options->WildCards = TRUE;
else
ErrorOption(OriginalArg);
break;
default :
ErrorOption(OriginalArg);
}
return ErrorCount == 0;
}
int main(int argc, char **argv)
{
static COMPILE_OPTIONS CompileOptions =
{
0, /* processor type = 8088 */
1, /* byte alignment */
FALSE, /* compile and link */
's', /* assume small memory model */
FALSE, /* do not assume SS != DS */
TRUE, /* Assume Windows executable, not DOS */
FALSE, /* assume .exe, not .dll */
FALSE, /* assume .exe, not .com */
FALSE, /* assume no debugging information */
FALSE, /* assume no stack checking */
FALSE, /* assume C, not C++ */
NULL, /* don't know runname yet */
FALSE, /* assume Windows 3.1, not Windows 3.0 */
TRUE, /* do generate map file */
FALSE, /* don't be verbose */
FALSE, /* don't handle wildcards */
'\0', /* don't assume anything about prologue code */
0, /* assume smart callbacks */
NULL, /* default code segment name */
0, /* no optimization */
NULL, /* No library to update */
FALSE, /* user has not said -DSTRICT */
};
int i, j;
COMPILER *Compiler;
if(argc < 2)
Usage();
Compiler = GetCompiler();
if(!Compiler)
{
ErrorOutput("Please set your CC environment variable "
"to the name\r\nof the compiler you wish to use,\r\n"
"Microsoft = 'msc', Borland = 'bcc', Symantec = 'sc'\r\n"
"(Zortech support abandoned!)\r\n");
exit(EXIT_FAILURE);
}
for(i = 1; i < argc; ++i)
if(*argv[i] == '-' || *argv[i] == '/')
DoOption(argv[i], &CompileOptions);
else
break;
if(CompileOptions.Windows && CompileOptions.Strict == 0)
Macros[NMacros++] = "-DSTRICT";
if(ErrorCount > 0)
{
Usage();
exit(EXIT_FAILURE);
}
if(CompileOptions.Windows && !CompileOptions.Prologue)
CompileOptions.Prologue = CompileOptions.Dll ? 'd' : 's';
for(j=i; j < argc; ++j)
{
char *Ext = FindExtension(argv[j]);
if(!Ext || !*Ext || !STRICMP(Ext, "c")
|| !STRICMP(Ext, "obj") || !STRICMP(Ext, "cpp"))
{
if(!CompileOptions.RunName)
{
static char RunName[128];
CopyFileName(argv[j], RunName);
CompileOptions.RunName = RunName;
}
}
}
SortFiles(argv+i, FilesByExt, Extensions, "c");
#if 0
{
int i, j;
for(i = 0; i < 7; ++i)
{
fprintf(stderr, "[%d] '.%-3.3s' %d files\n", i,
FilesByExt[i].Extension, FilesByExt[i].NFiles);
for(j = 0; j < FilesByExt[i].NFiles; ++j)
fprintf(stderr, " '%s'\n", FilesByExt[i].Array[j]);
}
}
#endif
if( FilesByExt[EXT_C ].NFiles == 0
&& FilesByExt[EXT_CPP].NFiles == 0
&& FilesByExt[EXT_OBJ].NFiles == 0
)
{
fprintf(stderr, "You must supply at least one source or object file\n");
exit(EXIT_FAILURE);
}
if( FilesByExt[EXT_RC ].NFiles +
FilesByExt[EXT_RES].NFiles > 1
)
{
fprintf(stderr, "You can only specify one .rc or .res file.\n");
exit(EXIT_FAILURE);
}
for(i = 0; i < NMacros; ++i)
CmdArgs[NCmdArgs++] = Macros[i];
if(ErrorCount == 0)
Compiler->CompilerFunc(Compiler->CompilerType, &CompileOptions);
return EXIT_SUCCESS;
}
void CompileRc(enum COMPILER_TYPE Compiler, COMPILE_OPTIONS *Options)
{
int Status;
char RcFileName[128];
char *RC = (Compiler == BCC ? "brc" : "rc");
strcpy(RcFileName, "");
if(FilesByExt[EXT_RC].NFiles > 0)
strcpy(RcFileName, FilesByExt[EXT_RC].Array[0]);
else if(FilesByExt[EXT_RES].NFiles <= 0)
{
FILE *RcFile;
strcpy(RcFileName, Options->RunName);
strcat(RcFileName, ".rc");
RcFile = fopen(RcFileName, "r");
if(RcFile != NULL)
fclose(RcFile);
else
strcpy(RcFileName, "");
}
if(RcFileName[0])
{
memset(CmdArgs, 0, MAX_ARGS * sizeof(char *));
CmdArgs[0] = RC;
NCmdArgs = 1;
CmdArgs[NCmdArgs++] = "-r";
CmdArgs[NCmdArgs++] = RcFileName;
EchoArgs(CmdArgs, NCmdArgs);
Status = spawnvp(P_WAIT, CmdArgs[0], CmdArgs);
if(Status)
exit(EXIT_FAILURE);
}
memset(CmdArgs, 0, MAX_ARGS * sizeof(char *));
CmdArgs[0] = RC;
NCmdArgs = 1;
if(RcFileName[0])
{
*FindExtension(RcFileName) = '\0';
strcat(RcFileName, "res");
}
else
if(FilesByExt[EXT_RES].NFiles > 0)
strcpy(RcFileName, FilesByExt[EXT_RES].Array[0]);
else
{
FILE *RcFile;
strcpy(RcFileName, Options->RunName);
strcat(RcFileName, ".res");
RcFile = fopen(RcFileName, "r");
if(RcFile != NULL)
fclose(RcFile);
else
strcpy(RcFileName, "");
}
if(RcFileName[0])
{
char Target[128];
memset(CmdArgs, 0, MAX_ARGS * sizeof(char *));
CmdArgs[0] = RC;
NCmdArgs = 1;
if(Options->Windows30)
CmdArgs[NCmdArgs++] = "-30";
CmdArgs[NCmdArgs++] = RcFileName;
strcpy(Target, Options->RunName);
strcat(Target, Options->Dll ? ".dll" : ".exe");
CmdArgs[NCmdArgs++] = Target;
EchoArgs(CmdArgs, NCmdArgs);
Status = spawnvp(P_WAIT, CmdArgs[0], CmdArgs);
if(Status)
exit(EXIT_FAILURE);
}
if(Options->Dll)
{
char Dll[128];
char Lib[128];
strcpy(Dll, Options->RunName);
strcat(Dll, ".dll");
strcpy(Lib, Options->RunName);
strcat(Lib, ".lib");
memset(CmdArgs, 0, MAX_ARGS * sizeof(char *));
CmdArgs[0] = "implib";
NCmdArgs = 1;
CmdArgs[NCmdArgs++] = Lib;
CmdArgs[NCmdArgs++] = Dll;
EchoArgs(CmdArgs, NCmdArgs);
Status = spawnvp(P_WAIT, CmdArgs[0], CmdArgs);
if(Status)
exit(EXIT_FAILURE);
}
}
void Msc(enum COMPILER_TYPE Compiler, COMPILE_OPTIONS *Options)
{
int Status;
FILE *ResponseFile;
if(FilesByExt[EXT_C].NFiles == 0 && FilesByExt[EXT_CPP].NFiles == 0)
goto LINK;
ResponseFile = OpenFile("wddjcc.rsp", "w");
CmdArgs[0] = "cl";
// CmdArgs[NCmdArgs++] = "/c /f-";
CmdArgs[NCmdArgs++] = "/c ";
if(!Options->Verbose)
CmdArgs[NCmdArgs++] = "/nologo";
CmdArgs[NCmdArgs++] = "/W3";
if(Options->Debug >= 2)
CmdArgs[NCmdArgs++] = "/Zdie";
else if(Options->Debug >= 1)
CmdArgs[NCmdArgs++] = "/Zd";
if(Options->CPlusPlus)
CmdArgs[NCmdArgs++] = "/vmg";
//otherwise, can't declare pointer to mem func before class
if(Options->Optimize)
CmdArgs[NCmdArgs++] = "/Ox";
if(Options->Align == 1)
CmdArgs[NCmdArgs++] = "/Zp";
if(Options->CodeSegment && *Options->CodeSegment)
{
static char CodeSegment[64];
sprintf(CodeSegment, "/NT%s", Options->CodeSegment);
CmdArgs[NCmdArgs++] = CodeSegment;
}
/* >>> begin /G options */
{
static
char GOption[10];
char *Output = GOption;
int OptionOut;
OptionOut = FALSE;
if(Options->ProcessorType >= 1)
{
strcpy(Output, "/G"), Output += 2, OptionOut = TRUE;
*Output++ = Options->ProcessorType + '0';
}
if(Options->Windows)
{
if(!OptionOut)
strcpy(Output, "/G"), Output += 2, OptionOut = TRUE;
if(Options->NoSmart)
*Output++ = 'w';
else
*Output++ = Options->Dll ? 'D' : 'A';
}
if(!Options->StackCheck)
{
if(!OptionOut)
strcpy(Output, "/G"), Output += 2, OptionOut = TRUE;
*Output++ = 's';
}
if(OptionOut)
{
*Output++ = '\0';
CmdArgs[NCmdArgs++] = GOption;
}
}
/* <<< end /G options */
if(Options->Windows && !Options->NoSmart)
{
static char Prologue[7];
sprintf(Prologue, "/GE%cme", Options->Prologue);
CmdArgs[NCmdArgs++] = Prologue;
}
{
static
char AOption[5];
char *Output = AOption;
strcpy(Output, "/A"), Output += 2;
*Output++ = Options->MemoryModel ^ ' '; /* map to uppercase */
if(Options->Dll || Options->SsNeqDs)
*Output++ = 'w'; /* SS != DS */
*Output++ = '\0';
CmdArgs[NCmdArgs++] = AOption;
}
{
int i;
char Path[128];
for(i = 0; i < FilesByExt[EXT_C].NFiles; ++i)
{
CopyPathName(FilesByExt[EXT_C].Array[i], Path);
fprintf(ResponseFile, " %s%s.c", Options->CPlusPlus
? "/Tp" : "", Path);
}
for(i = 0; i < FilesByExt[EXT_CPP].NFiles; ++i)
{
CopyPathName(FilesByExt[EXT_CPP].Array[i], Path);
fprintf(ResponseFile, " %s.cpp", Path);
}
}
fclose(ResponseFile);
strcpy(CommandLine, "@wddjcc.rsp");
CmdArgs[NCmdArgs++] = CommandLine;
EchoArgs(CmdArgs, NCmdArgs);
Status = spawnvp(P_WAIT, CmdArgs[0], CmdArgs);
if(!Options->Verbose)
unlink("@wddjcc.rsp");
if(Status)
exit(EXIT_FAILURE);
if(Options->CompileOnly)
return;
else
{
int Status;
int i;
char Path[128];
LINK:
NCmdArgs = 1;
memset(CmdArgs, 0, MAX_ARGS * sizeof(char *));
CmdArgs[0] = "link";
ResponseFile = OpenFile("wddjln.rsp", "w");
CmdArgs[NCmdArgs++] = "/nologo";
CmdArgs[NCmdArgs++] = "/NOE";
if(Options->Windows)
{
CmdArgs[NCmdArgs++] = "/align:16";
CmdArgs[NCmdArgs++] = "/NOD";
}
if(Options->MapFile)
CmdArgs[NCmdArgs++] = "/MAP:FULL /LINE";
if(Options->Debug > 0)
CmdArgs[NCmdArgs++] = "/CO";
for(i = 0; i < FilesByExt[EXT_C].NFiles; ++i)
{
CopyPathName(FilesByExt[EXT_C].Array[i], Path);
fprintf(ResponseFile, " %s.obj", Path);
}
for(i = 0; i < FilesByExt[EXT_CPP].NFiles; ++i)
{
CopyPathName(FilesByExt[EXT_CPP].Array[i], Path);
fprintf(ResponseFile, " %s.obj", Path);
}
for(i = 0; i < FilesByExt[EXT_OBJ].NFiles; ++i)
{
CopyPathName(FilesByExt[EXT_OBJ].Array[i], Path);
fprintf(ResponseFile, " %s.obj", Path);
}
if(Options->WildCards)
fprintf(ResponseFile, " setargv.obj");
fprintf(ResponseFile, ",\n");
fprintf(ResponseFile, "%s.%s", Options->RunName,
Options->Com ? "com" : Options->Dll ? "dll" : "exe");
fprintf(ResponseFile, ",\n");
fprintf(ResponseFile, "%s,\n",
Options->MapFile ? Options->RunName : "NUL.MAP");
if(Options->Windows)
{
for(i = 0; i < FilesByExt[EXT_LIB0].NFiles; ++i)
{
CopyPathName(FilesByExt[EXT_LIB0].Array[i], Path);
fprintf(ResponseFile, "%s.lib + ", Path);
}
fprintf(ResponseFile, "%c%scew", Options->MemoryModel,
Options->Dll ? "dll" : "lib");
for(i = 0; i < FilesByExt[EXT_LIB1].NFiles; ++i)
{
CopyPathName(FilesByExt[EXT_LIB1].Array[i], Path);
fprintf(ResponseFile, " + %s.lib", Path);
}
fprintf(ResponseFile, " + libw");
}
for(i = 0; i < FilesByExt[EXT_LIB].NFiles; ++i)
{
CopyPathName(FilesByExt[EXT_LIB].Array[i], Path);
fprintf(ResponseFile, " + %s.lib", Path);
}
fprintf(ResponseFile, ",\n");
if(Options->Windows)
{
if(FilesByExt[EXT_DEF].NFiles)
fprintf(ResponseFile, "%s\n", FilesByExt[EXT_DEF].Array[0]);
else
{
GenModDef(Options->RunName, Options->Dll);
fprintf(ResponseFile, "%s.def\n", Options->RunName);
}
}
fprintf(ResponseFile, ";\n");
fclose(ResponseFile);
CmdArgs[NCmdArgs++] = "@wddjln.rsp";
EchoArgs(CmdArgs, NCmdArgs);
Status = spawnvp(P_WAIT, CmdArgs[0], CmdArgs);
if(!Options->Verbose)
unlink("@wddjln.rsp");
if(Status)
exit(EXIT_FAILURE);
if(Options->Windows)
CompileRc(Compiler, Options);
}
}
void Bcc(enum COMPILER_TYPE Compiler, COMPILE_OPTIONS *Options)
{
int Status;
FILE *ResponseFile;
FILE *ConfigFile;
if(FilesByExt[EXT_C].NFiles == 0 && FilesByExt[EXT_CPP].NFiles == 0)
goto LINK;
ResponseFile = OpenFile("wddjcc.rsp", "w");
CmdArgs[0] = "bcc";
ConfigFile = OpenFile("wddjcc.cfg", "w");
CmdArgs[NCmdArgs++] = "-c";
if(getenv("INCLUDE"))
fprintf(ConfigFile, "-I%s\n", getenv("INCLUDE"));
if(getenv("LIB"))
fprintf(ConfigFile, "-L%s\n", getenv("LIB"));
if(Options->ProcessorType >= 1)
fprintf(ConfigFile, " -%c", '0' + Options->ProcessorType);
if(Options->Optimize)
CmdArgs[NCmdArgs++] = "-Ox-a";
if(Options->Align >= 2)
CmdArgs[NCmdArgs++] = "-a";
{
static char ModelOption[5];
sprintf(ModelOption, "-m%c%s", Options->MemoryModel,
Options->SsNeqDs ? "!" : "");
CmdArgs[NCmdArgs++] = ModelOption;
}
if(Options->Windows)
{
char *WindowOption;
if(Options->NoSmart)
WindowOption = Options->Dll ? "-WD" : "-WE";
else
switch(Options->Prologue)
{
case 'a' : /* load from AX */
WindowOption = "-WE";
break;
case 'd' : /* load from DGROUP */
WindowOption = "-WDE";
break;
case 's' : /* load from SS */
WindowOption = "-WS";
break;
}
CmdArgs[NCmdArgs++] = WindowOption;
}
else if(Options->Com)
CmdArgs[NCmdArgs++] = "-tDc -lt";
if(Options->Debug > 1)
CmdArgs[NCmdArgs++] = "-v";
else if(Options->Debug > 0)
CmdArgs[NCmdArgs++] = "-y";
if(Options->StackCheck)
CmdArgs[NCmdArgs++] = "-N";
if(Options->CodeSegment && *Options->CodeSegment)
{
static char CodeSegment[64];
sprintf(CodeSegment, "-zC%s", Options->CodeSegment);
CmdArgs[NCmdArgs++] = CodeSegment;
}
if(Options->CPlusPlus) /* if using C++ */
CmdArgs[NCmdArgs++] = "-P";
{
int i;
char Path[128];
for(i = 0; i < FilesByExt[EXT_C].NFiles; ++i)
{
CopyPathName(FilesByExt[EXT_C].Array[i], Path);
fprintf(ResponseFile, " %s.c", Path);
}
for(i = 0; i < FilesByExt[EXT_CPP].NFiles; ++i)
{
CopyPathName(FilesByExt[EXT_CPP].Array[i], Path);
fprintf(ResponseFile, " %s.cpp", Path);
}
}
fclose(ResponseFile);
fclose(ConfigFile);
strcpy(CommandLine, "+wddjcc.cfg");
strcat(CommandLine, " @wddjcc.rsp");
CmdArgs[NCmdArgs++] = CommandLine;
EchoArgs(CmdArgs, NCmdArgs);
Status = spawnvp(P_WAIT, CmdArgs[0], CmdArgs);
if(!Options->Verbose)
{
unlink("wddjcc.cfg");
unlink("wddjcc.rsp");
}
if(Status)
exit(EXIT_FAILURE);
LINK:
if(Options->LibName)
{
int i;
char Path[128];
NCmdArgs = 1;
memset(CmdArgs, 0, MAX_ARGS * sizeof(char *));
CmdArgs[0] = "tlib";
ResponseFile = OpenFile("wddjlb.rsp", "w");
CmdArgs[NCmdArgs++] = Options->LibName;
CmdArgs[NCmdArgs++] = "/C"; /* case-sensitive library */
for(i = 0; i < FilesByExt[EXT_C].NFiles; ++i)
{
CopyPathName(FilesByExt[EXT_C].Array[i], Path);
fprintf(ResponseFile, "-+%s.obj ", Path);
}
for(i = 0; i < FilesByExt[EXT_CPP].NFiles; ++i)
{
CopyPathName(FilesByExt[EXT_CPP].Array[i], Path);
fprintf(ResponseFile, "-+%s.obj ", Path);
}
for(i = 0; i < FilesByExt[EXT_OBJ].NFiles; ++i)
{
CopyPathName(FilesByExt[EXT_OBJ].Array[i], Path);
fprintf(ResponseFile, "-+%s.obj ", Path);
}
fclose(ResponseFile);
CmdArgs[NCmdArgs++] = "@wddjlb.rsp";
EchoArgs(CmdArgs, NCmdArgs);
Status = spawnvp(P_WAIT, CmdArgs[0], CmdArgs);
if(!Options->Verbose)
unlink("wddjlb.rsp");
if(Status)
exit(EXIT_FAILURE);
}
if(Options->CompileOnly)
return;
else
{
int Status;
int i;
char Path[128];
NCmdArgs = 1;
memset(CmdArgs, 0, MAX_ARGS * sizeof(char *));
CmdArgs[0] = "tlink";
ResponseFile = OpenFile("wddjln.rsp", "w");
if(getenv("LIB"))
fprintf(ResponseFile, " /L%s +\n", getenv("LIB"));
CmdArgs[NCmdArgs++] = "/A=16";
CmdArgs[NCmdArgs++] = "/c";
if(Options->Debug > 0)
CmdArgs[NCmdArgs++] = "/v";
if(Options->MapFile)
CmdArgs[NCmdArgs++] = "/l /s";
else
CmdArgs[NCmdArgs++] = "/x";
if(Options->Com)
CmdArgs[NCmdArgs++] = "/Tdc";
else if(Options->Windows)
{
if(Options->Dll)
CmdArgs[NCmdArgs++] = "/Twd";
else
CmdArgs[NCmdArgs++] = "/Twe";
}
else
CmdArgs[NCmdArgs++] = "/Tde";
fprintf(ResponseFile, "c0");
if(Options->Windows)
fprintf(ResponseFile, "%c", Options->Dll ? 'd' : 'w');
fprintf(ResponseFile, "%c.obj", Options->MemoryModel);
if(Options->WildCards)
{
char Path[128];
if(!SearchPath(getenv("LIB"), "wildargs.obj", Path))
fprintf(stderr, "Warning: Could not locate wildargs.obj\n");
else
fprintf(ResponseFile, " + %s", Path);
}
for(i = 0; i < FilesByExt[EXT_C].NFiles; ++i)
{
CopyPathName(FilesByExt[EXT_C].Array[i], Path);
fprintf(ResponseFile, " + %s.obj", Path);
}
for(i = 0; i < FilesByExt[EXT_CPP].NFiles; ++i)
{
CopyPathName(FilesByExt[EXT_CPP].Array[i], Path);
fprintf(ResponseFile, " + %s.obj", Path);
}
for(i = 0; i < FilesByExt[EXT_OBJ].NFiles; ++i)
{
CopyPathName(FilesByExt[EXT_OBJ].Array[i], Path);
fprintf(ResponseFile, " + %s.obj", Path);
}
fprintf(ResponseFile, ",+\n");
fprintf(ResponseFile, "%s.%s", Options->RunName,
Options->Com ? "com" : Options->Dll ? "dll" : "exe");
fprintf(ResponseFile, ",+\n");
fprintf(ResponseFile, ",+\n");
if(Options->Windows)
{
for(i = 0; i < FilesByExt[EXT_LIB0].NFiles; ++i)
{
CopyPathName(FilesByExt[EXT_LIB0].Array[i], Path);
fprintf(ResponseFile, "%s.lib + ", Path);
}
fprintf(ResponseFile, "cw%c.lib",
Options->MemoryModel);
for(i = 0; i < FilesByExt[EXT_LIB1].NFiles; ++i)
{
CopyPathName(FilesByExt[EXT_LIB1].Array[i], Path);
fprintf(ResponseFile, " + %s.lib", Path);
}
fprintf(ResponseFile, " + import");
}
else
fprintf(ResponseFile, "c%c.lib",
Options->MemoryModel == 't' ? 's' : Options->MemoryModel);
for(i = 0; i < FilesByExt[EXT_LIB].NFiles; ++i)
{
CopyPathName(FilesByExt[EXT_LIB].Array[i], Path);
fprintf(ResponseFile, " + %s.lib", Path);
}
if(Options->Windows)
{
fprintf(ResponseFile, ",+\n");
if(FilesByExt[EXT_DEF].NFiles)
fprintf(ResponseFile, "%s\n", FilesByExt[EXT_DEF].Array[0]);
else
{
GenModDef(Options->RunName, Options->Dll);
fprintf(ResponseFile, "%s.def\n", Options->RunName);
}
}
fclose(ResponseFile);
CmdArgs[NCmdArgs++] = "@wddjln.rsp";
EchoArgs(CmdArgs, NCmdArgs);
Status = spawnvp(P_WAIT, CmdArgs[0], CmdArgs);
if(!Options->Verbose)
unlink("wddjln.rsp");
if(Status)
exit(EXIT_FAILURE);
if(Options->Windows)
CompileRc(Compiler, Options);
}
}
void Ztc(enum COMPILER_TYPE Compiler, COMPILE_OPTIONS *Options)
{
static char MOption[10];
static char WOption[10];
int Status;
FILE *ResponseFile;
if(FilesByExt[EXT_C].NFiles == 0 && FilesByExt[EXT_CPP].NFiles == 0)
goto LINK;
ResponseFile = OpenFile("wddjcc.rsp", "w");
CmdArgs[0] = ((Compiler == SC) ? "sc" : "ztc");
CmdArgs[NCmdArgs++] = "-c";
if(Options->Verbose)
CmdArgs[NCmdArgs++] = "-v";
if(Options->CPlusPlus)
CmdArgs[NCmdArgs++] = "-cpp";
if(Options->ProcessorType >= 1)
{
static
char POption[8];
sprintf(POption, "-%d", Options->ProcessorType);
CmdArgs[NCmdArgs++] = POption;
}
if(Options->Optimize)
CmdArgs[NCmdArgs++] = "-o";
{
static char Align[4];
sprintf(Align, "-a%d", Options->Align);
CmdArgs[NCmdArgs++] = Align;
}
sprintf(MOption, "-m%c%s%s", Options->MemoryModel,
Options->SsNeqDs ? "w" : "",
(Options->Prologue == 'd') ? "u" : "");
CmdArgs[NCmdArgs++] = MOption;
if(Options->Windows)
{
if(Options->Prologue == 'a' || Options->Prologue == 'd')
strcpy(WOption, "-W2");
else if(Options->Prologue == 's')
strcpy(WOption, "-W3");
CmdArgs[NCmdArgs++] = WOption;
}
if(Options->Debug > 1)
CmdArgs[NCmdArgs++] = "-g";
else if(Options->Debug > 0)
CmdArgs[NCmdArgs++] = "-gl";
if(Options->CodeSegment && *Options->CodeSegment)
{
static char CodeSegment[64];
sprintf(CodeSegment, "-NT%s", Options->CodeSegment);
CmdArgs[NCmdArgs++] = CodeSegment;
}
if(Options->StackCheck)
CmdArgs[NCmdArgs++] = "-s";
{
int i;
char Path[128];
for(i = 0; i < FilesByExt[EXT_C].NFiles; ++i)
{
CopyPathName(FilesByExt[EXT_C].Array[i], Path);
fprintf(ResponseFile, " %s.c", Path);
}
for(i = 0; i < FilesByExt[EXT_CPP].NFiles; ++i)
{
CopyPathName(FilesByExt[EXT_CPP].Array[i], Path);
fprintf(ResponseFile, " %s.cpp", Path);
}
}
fclose(ResponseFile);
CmdArgs[NCmdArgs++] = "@wddjcc.rsp";
EchoArgs(CmdArgs, NCmdArgs);
Status = spawnvp(P_WAIT, CmdArgs[0], CmdArgs);
if(!Options->Verbose)
unlink("wddjcc.rsp");
if(Status)
exit(EXIT_FAILURE);
if(Options->CompileOnly)
return;
else
{
char *Plus = "";
int Status;
int i;
char Path[128];
LINK:
NCmdArgs = 1;
memset(CmdArgs, 0, MAX_ARGS * sizeof(char *));
CmdArgs[0] = ((Compiler == SC) ? "link" : "blinkx");
ResponseFile = OpenFile("wddjln.rsp", "w");
CmdArgs[NCmdArgs++] = "/nologo";
if(Options->Debug > 0)
CmdArgs[NCmdArgs++] = "/debug/codeview:4";
if(Options->MapFile)
CmdArgs[NCmdArgs++] = "/map";
if(!Options->Windows)
CmdArgs[NCmdArgs++] = "/dosseg";
if(Options->Verbose)
CmdArgs[NCmdArgs++] = "/information";
Plus = "";
if(Options->MemoryModel == 't')
fprintf(ResponseFile, "ct.obj"), Plus = " + ";
for(i = 0; i < FilesByExt[EXT_C].NFiles; ++i)
{
CopyPathName(FilesByExt[EXT_C].Array[i], Path);
fprintf(ResponseFile, "%s%s.obj", Plus, Path);
Plus = " + ";
}
for(i = 0; i < FilesByExt[EXT_CPP].NFiles; ++i)
{
CopyPathName(FilesByExt[EXT_CPP].Array[i], Path);
fprintf(ResponseFile, "%s%s.obj", Plus, Path);
Plus = " + ";
}
if(Options->Com)
{
fprintf(ResponseFile, "%sct.obj", Plus);
Plus = " + ";
}
for(i = 0; i < FilesByExt[EXT_OBJ].NFiles; ++i)
{
CopyPathName(FilesByExt[EXT_OBJ].Array[i], Path);
fprintf(ResponseFile, "%s%s.obj", Plus, Path);
Plus = " + ";
}
fprintf(ResponseFile, "\n");
fprintf(ResponseFile, "%s.%s", Options->RunName,
Options->Dll ? "dll" : "exe");
fprintf(ResponseFile, "\n");
fprintf(ResponseFile, "\n");
Plus = "";
for(i = 0; i < FilesByExt[EXT_LIB].NFiles; ++i)
{
CopyPathName(FilesByExt[EXT_LIB].Array[i], Path);
fprintf(ResponseFile, "%s%s.lib", Plus, Path);
Plus = " + ";
}
if(Options->Windows)
{
fprintf(ResponseFile, "\n");
if(FilesByExt[EXT_DEF].NFiles)
fprintf(ResponseFile, "%s\n", FilesByExt[EXT_DEF].Array[0]);
else
{
GenModDef(Options->RunName, Options->Dll);
fprintf(ResponseFile, "%s.def\n", Options->RunName);
}
}
fclose(ResponseFile);
CmdArgs[NCmdArgs++] = "@wddjln.rsp";
EchoArgs(CmdArgs, NCmdArgs);
Status = spawnvp(P_WAIT, CmdArgs[0], CmdArgs);
if(!Options->Verbose)
unlink("wddjln.rsp");
if(Status)
exit(EXIT_FAILURE);
if(Options->Windows)
CompileRc(Compiler, Options);
if(Options->Com)
{
char Path[128];
NCmdArgs = 1;
memset(CmdArgs, 0, MAX_ARGS * sizeof(char *));
CmdArgs[0] = "exe2bin";
sprintf(Path, "%s.exe %s.com", Options->RunName, Options->RunName);
CmdArgs[NCmdArgs++] = Path;
EchoArgs(CmdArgs, NCmdArgs);
execvp(CmdArgs[0], CmdArgs);
}
}
}